#include "ModbusServer.h"
#include <QModbusRtuSerialSlave>
#include <QModbusTcpServer>
#include <QRegularExpression>
#include <QRegularExpressionValidator>
#include <QStatusBar>
#include <QUrl>
#include <QDebug>
#include <QHostAddress>
#include <QNetworkInterface>

QString getIP() //获取ip地址
{
    QList<QHostAddress> list =QNetworkInterface::allAddresses();
    foreach (QHostAddress address, list)
    {
       if(address.protocol() ==QAbstractSocket::IPv4Protocol)
           return address.toString();
    }
    return "";
}


ModbusServer::ModbusServer(QObject *parent) : QObject(parent)
{
    modbusDevice = new QModbusTcpServer(this);
    QModbusDataUnitMap reg;
    reg.insert(QModbusDataUnit::HoldingRegisters, { QModbusDataUnit::HoldingRegisters, 2000, 1024 });
    modbusDevice->setMap(reg);

    connect(modbusDevice, &QModbusServer::dataWritten,  this, &ModbusServer::onRegisterChanged);
    connect(modbusDevice, &QModbusServer::stateChanged, this, &ModbusServer::onStateChanged);
    connect(modbusDevice, &QModbusServer::errorOccurred,this, &ModbusServer::handleDeviceError);

}

ModbusServer::~ModbusServer()
{
    Close();
}

void ModbusServer::setValue(const QString &name, const QVariant &value)
{
    if(name == "OK" && value.toString() == "Clear")
        OK = 0;
    else if(name == "NG" && value.toString() == "Clear")
        NG = 0;
    else if(name == "SolutionChange"){
        //设置solution
        //
        modbusDevice->setData(QModbusDataUnit::HoldingRegisters, 2015, value.toUInt());
        modbusDevice->setData(QModbusDataUnit::HoldingRegisters, 2014, 1U);
    }else if(name =="Connect"){
        Open(value.toString());
    }else if(name =="Disconnect"){
        Close();
    }

}

void ModbusServer::Open(QString ipaddress)
{
    Close();
    const QUrl url = QUrl::fromUserInput(ipaddress);
    modbusDevice->setConnectionParameter(QModbusDevice::NetworkPortParameter, url.port());
    modbusDevice->setConnectionParameter(QModbusDevice::NetworkAddressParameter, url.host());
    modbusDevice->setServerAddress(1);
    qDebug()<<tr("connect %1").arg(ipaddress);
    if (!modbusDevice->connectDevice())
    {
        qDebug()<<"connect Device failed!";
    }
}

void ModbusServer::Close()
{
    if(modbusDevice->ConnectedState == ::QModbusDevice::ConnectedState)
        modbusDevice->disconnectDevice();

    qDebug()<<"Close Device!";
}

void ModbusServer::onStateChanged(int state)
{
    if (state == QModbusDevice::UnconnectedState)
        qDebug()<<"unconectedState";
    else if (state == QModbusDevice::ConnectedState)
        qDebug()<<"connectedState";
}

void ModbusServer::onRegisterChanged(QModbusDataUnit::RegisterType table, int address, int size)
{
    for(quint16  i = 0; i < size; i++)
    {
        quint16 registerAddress = address+i;
        quint16 registerValue;

        modbusDevice->data(table, registerAddress, &registerValue);
       // qDebug()<<registerAddress<<"=="<<registerValue;
        switch(registerAddress)
        {
        case 2017:
            if(registerValue ==1)
            {
                OK++;
                modbusDevice->setData(table, registerAddress, 0U);
                emit newDataReady("OK", OK);
            }
            else if(registerValue ==2)
            {
                NG++;
                modbusDevice->setData(table, registerAddress, 0U);
                emit newDataReady("NG", NG);
            }
            break;

        case 2012:
            if(registerValue == 1)
            {
                modbusDevice->data(table, registerAddress+1, &registerValue);
                modbusDevice->setData(table, registerAddress, 0U);
                emit newDataReady("SolutionAdd", registerValue);
            }
            break;
        case 2016:
            if(registerValue != 0)
            {
                modbusDevice->setData(table, registerAddress, 0U);
                emit newDataReady("message", QString("solution change state:%1").arg(registerValue));
            }
            break;
        default:
            break;
        }
    }
}

void ModbusServer::handleDeviceError(QModbusDevice::Error newError)
{
    if (newError == QModbusDevice::NoError || !modbusDevice)
        return;
}
